iT邦幫忙

2022 iThome 鐵人賽

DAY 9
0
Software Development

這些年,我們早該學會的Spring Framework系列 第 9

Day09 - Dependency Injection (4)

  • 分享至 

  • xImage
  •  

Review

Container的職責在於創建、配置與組裝bean,昨天我們學到了

  • 為屬性的屬性賦值
  • bean配置的重用
    • 繼承重用
    • abstract template bean
  • Bean Scopes
    • singleton
    • prototype

今日將討論Spring如何設定工廠來產生所要的物件

前言

在介紹前,我們先參考一下wiki對工廠方法的介紹「定義一個建立物件的介面,但讓實現這個介面的類來決定實例化哪個類。工廠方法讓類別的實例化推遲到子類中進行。」簡單說就是透過某些條件決定實例化哪的子類別,工廠類型又可以分為

  • 靜態工廠
  • 實例工廠

以下簡化說明讓工廠只產生Car,先設定一下今日用到的程式碼

public class Car {
    private String type;//類型;跑車、休旅車
    private  int seat;//座位數
    private String color;
    public Car() {
        System.out.println("Car被創建...");
    }
    //getter setter toString略
}
//靜態工廠
public class CarStaticFactory {
    public static Car getCar(String type){
        System.out.println("靜態工廠製造汽車...");
        Car car = new Car();
        car.setColor("red");
        car.setSeat(4);
        car.setType(type);
        return car;
    }
}
//實例工廠
public class CarFactory {
    public Car getCar(String type){
        System.out.println("實例工廠製造汽車...");
        Car car = new Car();
        car.setColor("red");
        car.setSeat(4);
        car.setType(type);
        return car;
    }
}

靜態工廠創建bean

  • class指定工廠類別
  • factory-method指定工廠方法
  • 透過constructor-arg為工廠方法傳參數
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!-- 指定工廠類與工廠方法 -->
    <bean id="car01" class="com.swj.CarStaticFactory" factory-method="getCar">
        <constructor-arg value="跑車"></constructor-arg>
    </bean>
</beans>
@Test
public void testDay09(){
    ApplicationContext ioc = new ClassPathXmlApplicationContext("bean09.xml");
    System.out.println("容器啟動完成....");
    Car car = ioc.getBean("car01",Car.class);
    System.out.println(car);
}

Result
https://ithelp.ithome.com.tw/upload/images/20220924/20128084SHVzxyc8Xr.jpg

實例工廠創建bean

  • 需要先創建實例工廠的bean
  • factory-bean指定工廠實例
  • factory-method指定使用哪個工廠方法
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <!-- 實例工廠的bean需要先創建   -->
    <bean id="carFactory" class="com.swj.CarFactory"></bean>

    <bean id="car02" class="com.swj.Car" factory-bean="carFactory" factory-method="getCar">
        <constructor-arg name="type" value="休旅車"></constructor-arg>
    </bean>
</beans>
@Test
public void testDay09(){
    ApplicationContext ioc = new ClassPathXmlApplicationContext("bean09.xml");
    System.out.println("容器啟動完成....");
    Car car02 = ioc.getBean("car02",Car.class);
    System.out.println(car02);
}

Result
https://ithelp.ithome.com.tw/upload/images/20220924/20128084eEd3EGcdZC.jpg

FactoryBean

由Spring提供的工廠接口,implements此Interface,配置的bean會自動調用工廠方法創建bean

  • 容器啟動時不會創建實例,在調用物件時才會生成
  • 透過Interface的isSingleton方法可以設定該物件生成的是單例或多例

Spring提供的Interface

  • 2個需要的實作方法
  • 1個default方法,預設產生的物件為singleton
    https://ithelp.ithome.com.tw/upload/images/20220924/20128084vaYgUN1q0R.jpg
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="car03" class="com.swj.CarFactoryBean"></bean>
</beans>
public class CarFactoryBean implements FactoryBean {
    @Override
    public Object getObject() throws Exception {
        System.out.println("CarFactoryBean製造汽車");
        Car car = new Car();
        car.setType("公車");
        return car;
    }
    @Override
    public Class<?> getObjectType() {
        return Class.class;
    }
    @Override
    public boolean isSingleton() {
        return FactoryBean.super.isSingleton();
    }
}

測試

@Test
public void testDay09(){
    ApplicationContext ioc = new ClassPathXmlApplicationContext("bean09.xml");
    System.out.println("容器啟動完成....");
    Car car03 = ioc.getBean("car03",Car.class);
    System.out.println(car03);
}

Result
https://ithelp.ithome.com.tw/upload/images/20220924/20128084GZ7YpDPoFA.jpg

Reference


上一篇
Day08 - Dependency Injection (3)
下一篇
Day10 - Dependency Injection (5)
系列文
這些年,我們早該學會的Spring Framework30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言